package com.jetpackframework.virtualapk;

import android.app.Application;
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.ArrayMap;

import com.jetpackframework.ContextUtil;
import com.jetpackframework.Reflector;
import com.jetpackframework.virtual.VirtualApk;

import java.io.File;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class VirtualInstaller {
    private static VirtualInstaller installer;
    private Object activityManager;
    private ArrayMap<IBinder, Intent> mBoundServices = new ArrayMap<IBinder, Intent>();

    public static void install(Application application, Virtual virtual) {
        createInstrumentation(application);
        getInstance().activityManager = createActivityManager(application);
        try {
            VirtualManager.getInstance().loadApk(virtual.getApkPath());
        } catch (RemoteException e) {
            e.printStackTrace();
        }
//        Intent intent = new Intent(ContextUtil.get(),VirtualService.class);
//        VirtualServiceConnection.getInstance().setApkPath(virtual.getApkPath());
//        ContextUtil.get().bindService(intent,VirtualServiceConnection.getInstance(), Context.BIND_AUTO_CREATE);
    }


    private static Object createActivityManager(Application application) {
        Object activityManager = null;
        Object defaultSingleton = null;
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                defaultSingleton = Reflector.on("android.app.ActivityManager").field("IActivityManagerSingleton").get();
            } else {
                defaultSingleton = Reflector.on("android.app.ActivityManagerNative").field("gDefault").get();
            }
            Object origin = Reflector.with(defaultSingleton).method("get").call();

            activityManager = Proxy.newProxyInstance(application.getClassLoader(), new Class[]{Class.forName("android.app.IActivityManager")}, createActivityManagerProxy(origin));
            Reflector.with(defaultSingleton).field("mInstance").set(activityManager);
        }catch (Exception e){
            e.printStackTrace();
        }
        return activityManager;
    }

    private static InvocationHandler createActivityManagerProxy(Object origin) {
        return new ActivityManagerProxy(VirtualInstaller.getInstance(),origin);
    }

    public static synchronized VirtualInstaller getInstance() {
        if (installer == null){
            installer = new VirtualInstaller();
        }
        return installer;
    }

    private static void createInstrumentation(Application application) {
        try {
            Object activityThread = Reflector.on("android.app.ActivityThread").method("currentActivityThread").call();
            Instrumentation instrumentation = Reflector.with(activityThread).method("getInstrumentation").call();
            Instrumentation virtualInstrumentation = new VirtualInstrumentation(application,instrumentation);
            Reflector.with(activityThread).field("mInstrumentation").set(virtualInstrumentation);

            Handler handler = Reflector.with(activityThread).method("getHandler").call();
            Reflector.with(handler).field("mCallback").set(virtualInstrumentation);
        } catch (Reflector.ReflectedException e) {
            e.printStackTrace();
        }
    }

    public VirtualApk getVirtualApk(String packageName) {
        return VirtualManager.getInstance().getVirtualApk(packageName);
    }

    public Object getActivityManager() {
        return activityManager;
    }
    public void putServiceConnection(IBinder conn, Intent intent){
        mBoundServices.put(conn,intent);
    }
    public Intent forgetServiceConnection(IBinder conn){
        return mBoundServices.remove(conn);
    }
}
